﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using Workbench.Models;
using Workbench.Operations;
using Workbench.Persistance;
using Workbench.Presentation;

namespace WorkbenchTests
{
    [TestClass]
    public class ProjectTreeViewModelTests
    {
        [TestInitialize]
        public void Setup()
        {
            TestUtility.CreateAndInitializeTempDatabase();
        }

        [TestCleanup]
        public void TearDown()
        {
            ProjectOperations.CloseProject();
        }

        [TestMethod]
        public void ProjectTreeViewModelTests_IsSelectedIsMaintainedWell_With_clean_model()
        {
            var rootDirectory = new ProjectDirectoryModel() { Name = "Project node" };
            var vm = new ProjectTreeViewModel();
            var vmRootDirectory = new ProjectDirectoryViewModel(rootDirectory);
            vm.RootNodes.Add(vmRootDirectory);

            var lvl1Directory = new ProjectDirectoryModel() { Name = "Directory 1 node" };
            rootDirectory.Children.Add(lvl1Directory);
            var vmLvl1Directory = new ProjectDirectoryViewModel(lvl1Directory);
            vmRootDirectory.Children.Add(vmLvl1Directory);

            var lvl2Directory = new ProjectDirectoryModel() { Name = "Directory 2 node" };
            lvl1Directory.Children.Add(lvl2Directory);
            var vmLvl2Directory = new ProjectDirectoryViewModel(lvl2Directory);
            vmLvl1Directory.Children.Add(vmLvl2Directory);

            var lvl3Directory = new ProjectDirectoryModel() { Name = "Directory 3 node" };
            lvl2Directory.Children.Add(lvl3Directory);
            var vmLvl3Directory = new ProjectDirectoryViewModel(lvl3Directory);
            vmLvl2Directory.Children.Add(vmLvl3Directory);

            var file = new ProjectFileModel() { Name = "File 1 node" };
            lvl3Directory.Children.Add(file);
            var vmFile = new ProjectFileViewModel(file);
            vmLvl3Directory.Children.Add(vmFile);

            vmLvl1Directory.IsSelected = true;
            Assert.AreSame(vmLvl1Directory, vm.SelectedNode);

            vmLvl2Directory.IsSelected = true;
            Assert.AreSame(vmLvl2Directory, vm.SelectedNode);

            vmLvl3Directory.IsSelected = true;
            Assert.AreSame(vmLvl3Directory, vm.SelectedNode);

            vmRootDirectory.IsSelected = true;
            Assert.AreSame(vmRootDirectory, vm.SelectedNode);

            vmFile.IsSelected = true;
            Assert.AreSame(vmFile, vm.SelectedNode);
        }

        [TestMethod]
        public void ProjectTreeViewModelTests_IsSelectedIsMaintainedWell_With_initialized_model()
        {
            var rootDirectory = new ProjectDirectoryModel() { Name = "Project node" };
            var lvl1Directory = new ProjectDirectoryModel() { Name = "Directory 1 node" };
            var lvl2Directory = new ProjectDirectoryModel() { Name = "Directory 2 node" };
            var lvl3Directory = new ProjectDirectoryModel() { Name = "Directory 3 node" };
            var file = new ProjectFileModel() { Name = "File 1 node" };
            rootDirectory.Children.Add(lvl1Directory);
            lvl1Directory.Children.Add(lvl2Directory);
            lvl2Directory.Children.Add(lvl3Directory);
            lvl3Directory.Children.Add(file);

            var vm = new ProjectTreeViewModel();
            var vmRootDirectory = new ProjectDirectoryViewModel(rootDirectory);
            vm.RootNodes.Add(vmRootDirectory);
            var vmLvl1Directory = vmRootDirectory.Children[0] as ProjectDirectoryViewModel;
            var vmlvl2Directory = vmLvl1Directory.Children[0] as ProjectDirectoryViewModel;
            var vmlvl3Directory = vmlvl2Directory.Children[0] as ProjectDirectoryViewModel;
            var vmFile = vmlvl3Directory.Children[0] as ProjectFileViewModel;

            vmLvl1Directory.IsSelected = true;
            Assert.AreSame(vmLvl1Directory, vm.SelectedNode);

            vmlvl2Directory.IsSelected = true;
            Assert.AreSame(vmlvl2Directory, vm.SelectedNode);

            vmlvl3Directory.IsSelected = true;
            Assert.AreSame(vmlvl3Directory, vm.SelectedNode);

            vmRootDirectory.IsSelected = true;
            Assert.AreSame(vmRootDirectory, vm.SelectedNode);

            vmFile.IsSelected = true;
            Assert.AreSame(vmFile, vm.SelectedNode);
        }

        [TestMethod]
        public void ProjectTreeViewModelTests_Add_new_directory()
        {
            var rootDirectory = ProjectOperations.GetRootDirectory();

            var vm = new ProjectTreeViewModel();
            vm.RootNodes.Add(new ProjectDirectoryViewModel(rootDirectory));
            var projectNode = vm.RootNodes[0] as ProjectDirectoryViewModel;
            vm.CreateDirectory("New Folder", projectNode);

            Assert.AreEqual(1, projectNode.Children.Count);
            Assert.AreEqual("New Folder", projectNode.Children[0].Name);
        }

        [TestMethod]
        public void ProjectTreeViewModelTests_Add_new_directory_doesnt_crash_when_selected_is_null()
        {
            var rootDirectory = ProjectOperations.GetRootDirectory();

            var vm = new ProjectTreeViewModel();
            vm.RootNodes.Add(new ProjectDirectoryViewModel(rootDirectory));  
            vm.CreateDirectoryCommand.Execute(null);
        }

        [TestMethod]
        public void ProjectTreeViewModelTests_Add_existing_directory()
        {
            var rootDirectory = ProjectOperations.GetRootDirectory();
            var vm = new ProjectTreeViewModel();
            vm.RootNodes.Add(new ProjectDirectoryViewModel(rootDirectory));  

            var existingDirectoryName = Guid.NewGuid().ToString();
            var tempDirectoryPath = Path.Combine(Path.GetTempPath(), existingDirectoryName);
            Directory.CreateDirectory(tempDirectoryPath);
            string tempFileOnePath = Path.Combine(tempDirectoryPath, "File1.txt");
            string tempFileOneText = "This is the content of the first file";
            File.WriteAllText(Path.Combine(tempDirectoryPath, tempFileOnePath), tempFileOneText);
            string tempFileTwoPath = Path.Combine(tempDirectoryPath, "File2.txt");
            string tempFileTwoText = "This is the content of the second file";
            File.WriteAllText(Path.Combine(tempDirectoryPath, tempFileTwoPath), tempFileTwoText);

            var rootDirectoryViewModel = vm.RootNodes[0] as ProjectDirectoryViewModel;
            vm.AddExistingDirectory(tempDirectoryPath, rootDirectoryViewModel);

            Assert.AreEqual(1, rootDirectoryViewModel.Children.Count);
            var directoryNode = rootDirectoryViewModel.Children[0] as ProjectDirectoryViewModel;
            Assert.IsNotNull(directoryNode);
            Assert.AreEqual(existingDirectoryName, directoryNode.Name);

            Assert.AreEqual(2, directoryNode.Children.Count);
            Assert.AreEqual("File1.txt", directoryNode.Children[0].Name);
            Assert.AreEqual("File2.txt", directoryNode.Children[1].Name);
        }

        [TestMethod]
        public void ProjectTreeViewModelTests_Add_existing_file()
        {
            var rootDirectory = ProjectOperations.GetRootDirectory();

            var vm = new ProjectTreeViewModel();
            vm.RootNodes.Add(new ProjectDirectoryViewModel(rootDirectory));  

            var rootDirectoryViewModel = vm.RootNodes[0] as ProjectDirectoryViewModel;
            var existingDirectoryName = Guid.NewGuid().ToString();
            var tempDirectoryPath = Path.Combine(Path.GetTempPath(), existingDirectoryName);
            var tempFileOneName = "File1.txt";
            var tempFileOnePath = Path.Combine(tempDirectoryPath, tempFileOneName);
            var tempFileOneText = "This is the content of the first file";
            Directory.CreateDirectory(tempDirectoryPath);
            File.WriteAllText(Path.Combine(tempDirectoryPath, tempFileOnePath), tempFileOneText);

            vm.AddExistingFile(tempFileOnePath, rootDirectoryViewModel);

            Assert.AreEqual(1, rootDirectoryViewModel.Children.Count);
            var fileNode = rootDirectoryViewModel.Children[0] as ProjectFileViewModel;
            Assert.IsNotNull(fileNode);
            Assert.AreEqual(tempFileOneName, fileNode.Name);
        }
    }
}
